﻿using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Castle.Core;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using Castle.Windsor.Installer;
using NHibernate;

namespace GdNet.Integrations.Castle.Web
{
    public class CastleHttpApplication : HttpApplication
    {
        protected static IWindsorContainer Container;
        private static readonly IList<IWindsorInstaller> WindsorInstallers = new List<IWindsorInstaller>();

        #region Start

        protected void Application_Start()
        {
            OnApplicationStart();
            RegisterWindsorInstallers();
            BootstrapContainer();
        }

        /// <summary>
        /// Override this methods for additional tasks on Application_Start
        /// </summary>
        protected virtual void OnApplicationStart() { }

        protected virtual void RegisterWindsorInstallers()
        {
            AddWindsorInstaller(FromAssembly.Containing<CastleIntegrations>());
        }

        private static void BootstrapContainer()
        {
            Container = new WindsorContainer().Install(WindsorInstallers.ToArray());
            Container.Kernel.ComponentCreated += Kernel_ComponentCreated;
            Container.Kernel.ComponentDestroyed += Kernel_ComponentDestroyed;

            var controllerFactory = new WindsorControllerFactory(Container.Kernel);
            ControllerBuilder.Current.SetControllerFactory(controllerFactory);
        }

        static void Kernel_ComponentCreated(ComponentModel model, object instance)
        {
        }

        static void Kernel_ComponentDestroyed(ComponentModel model, object instance)
        {
        }

        #endregion

        #region BeginRequest

        protected void Application_BeginRequest()
        {
            OnApplicationBeginRequest();
        }

        protected virtual void OnApplicationBeginRequest()
        {
            Container.Resolve<ISession>().BeginTransaction();
        }

        #endregion

        #region EndRequest

        protected void Application_EndRequest()
        {
            OnApplicationEndRequest();
        }

        protected virtual void OnApplicationEndRequest()
        {
            // TODO: study to find a good solution to commit transaction
            //_container.Resolve<ISession>().Transaction.Commit();
        }

        #endregion

        protected void Application_End()
        {
            Container.Dispose();
        }

        protected static void AddWindsorInstaller(IWindsorInstaller installer)
        {
            if (!WindsorInstallers.Contains(installer))
            {
                WindsorInstallers.Add(installer);
            }
        }
    }
}
